package rbac.service.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import rbac.dao.UserDao;
import rbac.dao.UserGroupDao;
import rbac.entity.RbacUser;
import rbac.entity.RbacUserGroup;
import rbac.enums.EntityDoNotExistExceptionMessage;
import rbac.exception.DuplicateUserNameException;
import rbac.exception.EntityDoNotExistException;
import rbac.service.UserService;


/**
 * RBAC 用户管理 service 实现类.
 * 
 * @author Huadi
 * @author Zoufengyang
 */
@Service("userService")
public class UserServiceImpl implements UserService {

	@Autowired
	@Qualifier("userDao")
	private UserDao userDao;

	@Autowired
	private UserGroupDao userGroupDao;

	@Override
	public RbacUser getUser(String name) {
		return userDao.getUser(name);
	}

	@Override
	public RbacUser getUser(Integer id) {
		return userDao.getUser(id);
	}

	@Override
	public List<RbacUser> getAllUsers() {
		return userDao.getAllUsers();
	}

	@Override
	public void delete(RbacUser user) {
		userDao.delete(user);
	}

	@Override
	public void delete(Integer userId) {
		userDao.delete(userId);
	}

	@Override
	public void save(RbacUser user) throws DuplicateUserNameException {
		if (null == userDao.getUser(user.getUserName())) {
			userDao.save(user);
		} else {
			throw new DuplicateUserNameException();
		}
	}

	@Override
	public void update(RbacUser user) throws EntityDoNotExistException {
		if (null != userDao.getUser(user.getId())) {
			userDao.update(user);
		} else {
			throw new EntityDoNotExistException();
		}
	}

	@Override
	public void grantUserGroupToUser(RbacUserGroup userGroup, RbacUser user)
			throws EntityDoNotExistException {
		if (!user.getUserGroups().contains(userGroup)) {
			user.getUserGroups().add(userGroup);
			this.update(user);
		}
	}

	@Override
	public void grantUserGroupToUser(Integer userGroupId, Integer userId)
			throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}
		RbacUser user = this.getUser(userId);
		if (null == user) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserDoNotExist);
		}

		this.grantUserGroupToUser(userGroup, user);
	}

	@Override
	public void grantUserGroupToUser(Integer userGroupId, String userName)
			throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}
		RbacUser user = this.getUser(userName);
		if (null == user) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserDoNotExist);
		}

		this.grantUserGroupToUser(userGroup, user);
	}

	@Override
	public void revokeUserGroupFromUser(RbacUserGroup userGroup, RbacUser user)
			throws EntityDoNotExistException {
		if (user.getUserGroups().remove(userGroup)) {
			this.update(user);
		}
	}

	@Override
	public void revokeUserGroupFromUser(Integer userGroupId, Integer userId)
			throws EntityDoNotExistException {
		RbacUser user = this.getUser(userId);
		if (null == user) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserDoNotExist);
		}
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}

		this.revokeUserGroupFromUser(userGroup, user);
	}

	@Override
	public void revokeUserGroupFromUser(Integer userGroupId, String userName)
			throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserGroupDoNotExist);
		}
		RbacUser user = this.getUser(userName);
		if (null == user) {
			throw new EntityDoNotExistException(
					EntityDoNotExistExceptionMessage.UserDoNotExist);
		}

		this.revokeUserGroupFromUser(userGroup, user);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void grantUserGroupToUser(Integer userId,
			List<Integer> selectedUserGroupIds)
			throws EntityDoNotExistException {
		RbacUser user = userDao.getUser(userId);
		Set<RbacUserGroup> userGroupSet = new HashSet<RbacUserGroup>();
		for (Integer userGroupId : selectedUserGroupIds) {
			RbacUserGroup ug = userGroupDao.getUserGroup(userGroupId);
			if (null != ug) {
				userGroupSet.add(ug);
			}
		}
		user.setUserGroups(userGroupSet);
		this.update(user);
	}

	@Override
	public List<RbacUser> getUsers(Collection<Integer> userIds) {
		return userDao.getUsers(userIds);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor={Exception.class})
	public void grantUserGroupToUser(Integer userGroupId,
			Collection<String> userNames) throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		for (String name : userNames) {
			RbacUser user = this.getUser(name);
			if (null == user) {
				throw new EntityDoNotExistException();
			}
			user.getUserGroups().add(userGroup);
			try {
				this.update(user);
			} catch (EntityDoNotExistException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void revokeUserGroupFromUser(Integer userGroupId,
			Collection<String> userNames) throws EntityDoNotExistException {
		RbacUserGroup userGroup = userGroupDao.getUserGroup(userGroupId);
		if (null == userGroup) {
			throw new EntityDoNotExistException();
		}
		for (String userName : userNames) {
			RbacUser user = this.getUser(userName);
			user.getUserGroups().remove(userGroup);
			this.update(user);
		}
	}

}
